<template>
  <div :id="uuid" :key="uuid" class="w100">
    <div
      v-if="isFormShow"
      class="tagTreeFormItem"
      :style="{ maxHeight: isFullscreen ? '60vh' : '130px' }"
      @click="openDialog"
    >
      <div class="tagWrap">
        <el-tag
          size="small"
          closable
          v-for="(item, index) in confirmTagList"
          :key="index"
          @close="handleCloseTag(item, true)"
        >
          <span class="tagTest">
            {{
              isDepartmentShow ? `${item.department}/${item.name}` : `${item[defaultProps.label]}`
            }}
          </span>
        </el-tag>
      </div>
      <el-icon class="rightIcon"><ArrowRightBold /></el-icon>
    </div>
    <op-dialog
      ref="TreeDialogRef"
      destroy-on-close
      :title="title"
      @open="handleOpen"
      @close="handleClose"
      class="treeDialog"
      append-to-body
      @confirm="handleConfirm"
      size="big"
      height="auto"
    >
      <!-- v-model="treeDialogVisible" -->
      <!-- :width="width" -->
      <!-- @buttonClick="buttonClick" -->
      <!-- :handleButton="handleButton" -->
      <div v-loading.lock="loading">
        <div class="innerStaffWrap" v-if="selectType === '1'">
          <div class="innerStaffTitle">
            <span>Selected Staff {{ selectStaffList.length }}</span>
          </div>
          <div class="innerStaffBox">
            <el-tag
              v-for="(item, index) in selectStaffList"
              :key="index"
              type="info"
              style="margin: 0 6px 6px 0"
            >
              {{ item.userName }}</el-tag
            >
          </div>
        </div>
        <el-row :gutter="0">
          <el-col :span="10">
            <div
              class="innerTreeWrap"
              :style="{
                padding: selectType === '1' ? '0 10px 10px 10px' : '10px',
              }"
            >
              <div class="innerTreeAll" v-if="selectType === '1'">
                <el-radio-group v-model="departmentRadio" @change="handleRadioChange">
                  <el-radio label="All">All</el-radio>
                  <el-radio label="Designated">Designated</el-radio>
                </el-radio-group>
              </div>
              <el-input
                placeholder="Search or Select"
                v-model="filterText"
                clearable
                style="margin-bottom: 8px"
                :suffix-icon="Search"
              />
              <el-tree
                class="innerTreeBox"
                :style="{
                  height: selectType === '1' ? 'calc(100% - 80px)' : 'calc(100% - 50px)',
                }"
                :data="treeList"
                :props="defaultProps"
                :filter-node-method="filterNode"
                ref="TreeRef"
                :node-key="nodeKey"
                show-checkbox
                @check="handleCheck"
              />
            </div>
          </el-col>
          <el-col :span="14">
            <div
              class="innerTagWrap"
              :style="{
                padding: '10px',
                paddingRight: 0,
                paddingTop: selectType === '1' ? '0' : '10px',
              }"
            >
              <div class="innerTagTitle">
                <span>Selected {{ ' ' + tagList.length }}</span>
              </div>
              <div class="innerTagBox">
                <el-tag
                  closable
                  v-for="(item, index) in tagList"
                  :key="index"
                  @close="handleCloseTag(item)"
                >
                  {{
                    isDepartmentShow
                      ? `${item.department}/${item.name}`
                      : `${item[defaultProps.label]}`
                  }}
                </el-tag>
              </div>
              <el-icon
                v-if="tagList && tagList.length > 1"
                @click.stop="clearAll"
                class="rightIcon"
              >
                <CircleClose />
              </el-icon>
            </div>
          </el-col>
        </el-row>
      </div>
      <slot name="append" />
    </op-dialog>
  </div>
</template>

<script setup>
const idGen = () => new Date().getTime();
import { apiMethods } from '@/utils/http';

const emit = defineEmits(['selectConfirmed', 'cleared', 'itemEvent', 'destory']);

const {
  url,
  apiMethod,
  params,
  singleCheck,
  callbackID,
  modelValue,
  prop,
  defaultID,
  isFormShow,
  tier,
  nodeKey,
  selectType,
  defaultProps,
  selectStaffList,
  withFatherNode,
  ...props
} = defineProps({
  url: {
    type: String,
    default: '/loanTotal/getAllUserList',
  },
  apiMethod: {
    type: String,
    default: 'post',
  },
  // 接口参数
  params: {
    type: Object,
    default: () => {},
  },
  // 是否为单选
  singleCheck: {
    type: Boolean,
    default: false,
  },
  callbackID: {
    type: Function,
    default: () => {},
  },
  // width: {
  //   type: String,
  //   default: '60%',
  // },
  title: {
    type: String,
    default: 'Add Staff',
  },
  prop: {
    type: String,
    default: '',
  },
  // 若需要展示默认ID，请传入
  defaultID: {
    type: Array,
    default: () => [],
  },
  modelValue: {
    type: Array,
    default: () => [],
  },
  isDepartmentShow: {
    type: Boolean,
    default: false,
  },
  isFormShow: {
    type: Boolean,
    default: true,
  },
  isFullscreen: {
    type: Boolean,
    default: false,
  },
  // 若接口需处理层级或选择对象，请传入
  tier: {
    type: String,
    default: '',
  },
  // 每个树节点用来作为唯一标识的属性，整棵树应该是唯一的
  nodeKey: {
    type: String,
    default: 'realId',
  },
  // 若仅可选择人，请忽视，type=1，部门，type=2，项目，type=3,选择到人,type=4 new
  selectType: {
    type: String,
    default: '3',
  },
  selectStaffList: {
    type: Array,
    default: [],
  },
  // 配置选项
  defaultProps: {
    type: Object,
    default: () => ({
      label: 'name', // 显示名称
    }),
  },
  // 是否需要传入父节点给taglist展示和后端(每层全选都会将父节点传入)
  withFatherNode: {
    type: Boolean,
    default: false,
  },
});
const TreeRef = ref();
const TreeDialogRef = ref();

const uuid = ref(idGen());
const filterText = ref('');
const departmentRadio = ref('Designated');

const tagList = ref([]);
const confirmTagList = ref([]);
const treeList = ref([]);
const flattenTreeList = ref([]);
// const treeDialogVisible = ref(false);
const loading = ref(false);
const isReShow = ref(false);

onMounted(() => {
  initData();
});

function openDialog() {
  TreeDialogRef.value.init();
  if (!treeList.value.length) initData();
}

function closeDialog() {
  TreeDialogRef.value.destroy();
}

function initData() {
  getTreeList();
}

async function getTreeList() {
  loading.value = true;

  let res = await apiMethods[apiMethod](url, params);
  if (res.data.code === '200') {
    let arr = tier ? removeEmptyChildren(res.data.data[tier]) : removeEmptyChildren(res.data.data);
    treeList.value = [...arr];
    if (nodeKey === 'realId') {
      setId(treeList.value);
    }
    if (defaultID && defaultID.length > 0) setTaglist();
    if (modelValue && modelValue.length > 0) setTaglist();
  }
  loading.value = false;
}

function // 树形结构中删除空children
removeEmptyChildren(node) {
  node.forEach(item => {
    if ('children' in item && !item.children) {
      delete item.children;
    }
    if (item.children && item.children.length === 0) {
      delete item.children;
    } else if (item.children && item.children.length > 0) {
      removeEmptyChildren(item.children);
    }
  });
  return node;
}

function setTaglist() {
  if (!flattenTreeList.value.length) flattenTreeList.value = flatten(treeList.value);

  if (prop) {
    tagList.value = [];
    modelValue.forEach(item => {
      flattenTreeList.value.forEach(i => {
        if (item[nodeKey] === i[nodeKey]) {
          tagList.value.push(i);
        }
      });
    });
    confirmTagList.value = [...tagList.value];
  } else {
    defaultID.forEach(item => {
      flattenTreeList.value.forEach(i => {
        if (item === i.id) {
          tagList.value = [];
          tagList.value.push(i);
        }
      });
    });
  }
}

function flatten(arr) {
  return arr.reduce((result, item) => {
    return result.concat(item, Array.isArray(item.children) ? flatten(item.children) : []);
  }, []);
}

function handleConfirm() {
  if (tagList.value.length === 0)
    return ElMessage.warning(`Please select at least one piece of data`);
  confirmTagList.value = tagList.value;

  emit('selectConfirmed', confirmTagList.value, selectType);
  closeDialog();
}

// function buttonClick(prop) {
//   if (prop === 'cancel') {
//     clearAll();
//     closeDialog();
//   }
//   if (prop === 'confirm') {
//     if (tagList.value.length === 0)
//       return ElMessage.warning(`Please select at least one piece of data`);
//     confirmTagList.value = tagList.value;

//     emit('selectConfirmed', confirmTagList.value, selectType);
//     closeDialog();
//   }
// }

function clearAll() {
  isReShow.value = false;
  filterText.value = '';
  departmentRadio.value = 'Designated';
  tagList.value = [];
  callbackID(tagList.value);
  emit('cleared');

  // 对话框子组件时，若未首次打开不存在于DOM
  if (TreeRef.value) {
    TreeRef.value.setCheckedKeys([]);
  }
}

function handleOpen() {
  if (isFormShow) {
    tagList.value = confirmTagList.value;
    let arr = [];
    tagList.value.forEach(item => arr.push(item[nodeKey]));
    callbackID(tagList.value);
    emit('itemEvent', tagList.value);
    TreeRef.value.setCheckedKeys(arr);
  } else if (!isFormShow && isReShow.value) {
    if (selectStaffList.length > 0) {
      const departmentId = selectStaffList[0].managementScopeId.split(',');
      let realIdList = [];
      let realIdListNodes = [];
      let num = 0;
      flatten(treeList.value).forEach((item, index) => {
        if (!item.children) num++;
        departmentId.forEach((i, ind) => {
          if (item.id === i) {
            realIdList.push(item[nodeKey]);
            realIdListNodes.push(item);
          }
        });
      });
      TreeRef.value.setCheckedKeys(realIdList);
      multipleTag(realIdListNodes);
      if (tagList.value.length === num) departmentRadio.value = 'All';
    }
  }
}

function multipleTag(checkedNodes) {
  // 树形选择框 反选All radio
  checkedNodes.length === flatten(treeList.value).length
    ? (departmentRadio.value = 'All')
    : (departmentRadio.value = 'Designated');

  tagList.value = [];
  checkedNodes.forEach(item => {
    if (withFatherNode) {
      // 数据不混
      if (['4'].includes(selectType)) {
        tagList.value.push(item);
      }
      // 数据混在一起的情况（部门和人）
      else if (item.type == selectType) {
        tagList.value.push(item);
      }
    } else {
      if (!item.children) {
        // 数据不混
        if (['4'].includes(selectType)) {
          tagList.value.push(item);
        }
        // 数据混在一起的情况（部门和人）
        else if (item.type == selectType) {
          tagList.value.push(item);
        }
      }
    }
  });
  callbackID(tagList.value);
  emit('itemEvent', tagList.value);
}

function singleTag(data, checkedNodes) {
  tagList.value = [];

  TreeRef.value.setCheckedKeys([]);
  if (data.type === selectType && checkedNodes.length > 0) {
    tagList.value = [];
    tagList.value.push(data);

    TreeRef.value.setCheckedKeys([data.realId]);
  }
  callbackID(tagList.value);
  emit('itemEvent', tagList.value);
}

function handleClose() {
  clearAll();
  closeDialog();
  emit('destroy');
}

function // 数据中uesrid不唯一
setId(list) {
  list.forEach(item => {
    item.realId = item.id + '&' + item.parent;
    if (item.children?.length) {
      setId(item.children);
    }
  });
}

function findId(list, arr1, arr2) {
  list.forEach(item => {
    if (arr1.find(a => a === item.realId)) {
      arr2.push(item.realId);
    } else {
      arr1.push(item.realId);
    }
    if (item.children?.length) {
      findId(item.children, arr1, arr2);
    }
  });
}

function handleCloseTag(tag, closeConfirmTag) {
  let arr = [];
  if (closeConfirmTag) {
    confirmTagList.value = confirmTagList.value.filter(item => item[nodeKey] != tag[nodeKey]);
    confirmTagList.value.forEach(item => arr.push(item[nodeKey]));
    emit('itemEvent', confirmTagList.value);
    callbackID(confirmTagList.value);
  } else {
    tagList.value = tagList.value.filter(item => item[nodeKey] != tag[nodeKey]);
    tagList.value.forEach(item => arr.push(item[nodeKey]));
    emit('itemEvent', tagList.value);
    callbackID(tagList.value);
  }
  TreeRef.value.setCheckedKeys(arr);
  departmentRadio.value = 'Designated';
}

function handleRadioChange(departmentRadio) {
  if (departmentRadio === 'All') {
    const arr = flatten(treeList.value);
    let realIdList = [];
    arr.forEach(i => realIdList.push(i.realId));
    TreeRef.value.setCheckedKeys(realIdList);
    handleCheck([], { checkedNodes: arr });
  } else {
    clearAll();
  }
}

function // 树节点过滤
filterNode(value, data) {
  if (!value) return true;
  return data[defaultProps?.label].toLowerCase().indexOf(value.toLowerCase()) !== -1;
}

function // 树选中checkBox
handleCheck(data, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) {
  singleCheck ? singleTag(data, checkedNodes) : multipleTag(checkedNodes);
}

function setValue() {
  filterText.value = '';
  if (modelValue && modelValue.length > 0 && treeList.value.length > 0) {
    setTaglist();
  }
  if (modelValue && modelValue.length === 0) {
    tagList.value = [];
    if (TreeRef.value) TreeRef.value.setCheckedKeys([]);
  }
}

watch(
  () => filterText.value,
  val => {
    TreeRef.value.filter(val);
  }
);

watch(
  () => modelValue,
  () => setValue()
);
watch(
  () => defaultID,
  () => setValue()
);
</script>

<style scoped lang="scss">
.tagTreeFormItem {
  min-height: 26px;
  max-height: 130px;
  line-height: 26px;
  width: 100%;
  // padding: 0 4px;
  display: flex;
  justify-content: space-between;
  background-color: #fff;
  border: solid 1px rgb(220, 223, 230);
  border-radius: 4px;
  cursor: text;
  overflow: auto;
  .el-tag {
    margin: 0 2px;
  }
  .el-icon-circle-close {
    margin: 10px 10px 0 0;
    &:hover {
      color: #127bbc;
      cursor: pointer;
    }
  }
  .tagWrap {
    padding-right: 15px;
  }
}
.rightIcon {
  position: absolute;
  right: 15px;
  top: 50%;
  margin-top: -7px;
  cursor: pointer;
  &:hover {
    color: #127bbc;
  }
}

.treeDialog {
  .innerStaffWrap {
    padding: 0 10px 10px 10px;
    border: 1px solid rgb(220, 223, 230);
    margin-bottom: 10px;
    .innerStaffTitle {
      height: 30px;
      display: flex;
      align-items: center;
    }
    .innerStaffBox {
      height: 60px;
      overflow: auto;
    }
  }
  .innerTreeWrap {
    border: 1px solid rgb(220, 223, 230);
    border-right: 0;
    height: 46vh;

    .innerTreeAll {
      height: 30px;
    }

    .innerTreeBox {
      overflow: auto;
    }
  }
  .innerTagWrap {
    position: relative;
    height: 46vh;
    border: solid 1px rgb(220, 223, 230);
    .innerTagTitle {
      height: 30px;
      display: flex;
      align-items: center;
    }
    .innerTagBox {
      height: calc(100% - 40px);
      padding-right: 15px;
      overflow: auto;
      .el-tag {
        margin: 0 6px 6px 0;
      }
    }
    .el-icon-circle-close {
      position: absolute;
      right: 35px;
      top: 20px;
      &:hover {
        color: #127bbc;
        cursor: pointer;
      }
    }
  }
}

.treeTag {
  height: 40px;
  display: flex;
  justify-content: left;
  align-items: center;
  background: #f9fafb;
  border-radius: 4px;
  border: 1px solid #e5e6ec;
  padding: 10px;
  box-sizing: border-box;
  color: #606266;
  margin-top: 10px;
  :deep().el-tag__content {
    display: flex;
    align-items: center;
  }
}

.w100 {
  width: 100%;
}
</style>
